package cn.iocoder.yudao.module.project.service.order;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.module.project.controller.admin.internalcode.vo.InternalCodeWorkstationRespVO;
import cn.iocoder.yudao.module.project.dal.dataobject.defectiveproductrecord.DefectiveProductRecordDO;
import cn.iocoder.yudao.module.project.dal.dataobject.deliveryreceipt.DeliveryReceiptDO;
import cn.iocoder.yudao.module.project.dal.dataobject.deliveryreceiptdetail.DeliveryReceiptDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.deptcompletedlog.DeptCompletedLogDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalcode.InternalCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalworkstationplan.InternalWorkstationPlanDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehouse.KisMaterielExWarehouseDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehousehistory.KisMaterielExWarehouseHistoryDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehouserecycle.KisMaterielExWarehouseRecycleDO;
import cn.iocoder.yudao.module.project.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.productioncode.ProductionCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.productprocesscompleted.ProductProcessCompletedDO;
import cn.iocoder.yudao.module.project.dal.dataobject.weighthistory.WeightHistoryDO;
import cn.iocoder.yudao.module.project.dal.mysql.defectiveproductrecord.DefectiveProductRecordMapper;
import cn.iocoder.yudao.module.project.dal.mysql.deliveryreceipt.DeliveryReceiptMapper;
import cn.iocoder.yudao.module.project.dal.mysql.deliveryreceiptdetail.DeliveryReceiptDetailMapper;
import cn.iocoder.yudao.module.project.dal.mysql.deptcompletedlog.DeptCompletedLogMapper;
import cn.iocoder.yudao.module.project.dal.mysql.internalcode.InternalCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.internalworkstationplan.InternalWorkstationPlanMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kisbom.KisBomMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehouse.KisMaterielExWarehouseMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehousehistory.KisMaterielExWarehouseHistoryMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehouserecycle.KisMaterielExWarehouseRecycleMapper;
import cn.iocoder.yudao.module.project.dal.mysql.orderdetail.OrderDetailMapper;
import cn.iocoder.yudao.module.project.dal.mysql.productioncode.ProductionCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.productprocesscompleted.ProductProcessCompletedMapper;
import cn.iocoder.yudao.module.project.dal.mysql.weighthistory.WeightHistoryMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.project.controller.admin.order.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.project.dal.mysql.order.OrderMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.project.enums.ErrorCodeConstants.*;

/**
 * 生产订单信息 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private KisBomMapper kisBomMapper;

    @Resource
    private DeptCompletedLogMapper deptCompletedLogMapper;

    @Resource
    private DefectiveProductRecordMapper defectiveProductRecordMapper;

    @Resource
    private DeliveryReceiptMapper deliveryReceiptMapper;

    @Resource
    private DeliveryReceiptDetailMapper deliveryReceiptDetailMapper;

    @Resource
    private InternalCodeMapper internalCodeMapper;

    @Resource
    private KisMaterielExWarehouseMapper kisMaterielExWarehouseMapper;

    @Resource
    private KisMaterielExWarehouseHistoryMapper kisMaterielExWarehouseHistoryMapper;

    @Resource
    private KisMaterielExWarehouseRecycleMapper kisMaterielExWarehouseRecycleMapper;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private ProductProcessCompletedMapper productProcessCompletedMapper;

    @Resource
    private ProductionCodeMapper productionCodeMapper;

    @Resource
    private WeightHistoryMapper weightHistoryMapper;

    @Resource
    private InternalWorkstationPlanMapper internalWorkstationPlanMapper;

    @Override
    public String createOrder(OrderSaveReqVO createReqVO) {
        // 插入
        OrderDO order = BeanUtils.toBean(createReqVO, OrderDO.class);
        orderMapper.insert(order);
        // 返回
        return order.getId();
    }

    @Override
    public void updateOrder(OrderSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderExists(updateReqVO.getId());
        // 更新
        OrderDO updateObj = BeanUtils.toBean(updateReqVO, OrderDO.class);
        orderMapper.updateById(updateObj);
    }

    @Override
    @Transactional
    public void deleteOrder(String id) {
        // 校验存在
        validateOrderExists(id);
        // 删除
        orderMapper.delete(new QueryWrapper<OrderDO>().eq("id", id));

        defectiveProductRecordMapper.delete(DefectiveProductRecordDO::getOrderCode, id);

        deliveryReceiptMapper.delete(DeliveryReceiptDO::getOrderId, id);

        deliveryReceiptDetailMapper.delete(DeliveryReceiptDetailDO::getOrderId, id);

        deptCompletedLogMapper.delete(DeptCompletedLogDO::getOrderCode, id);

        internalWorkstationPlanMapper.delete(InternalWorkstationPlanDO::getOrderCode, id);

        internalCodeMapper.delete(InternalCodeDO::getOrderCode, id);

        kisMaterielExWarehouseMapper.delete(KisMaterielExWarehouseDO::getOrderCode, id);

        kisMaterielExWarehouseHistoryMapper.delete(KisMaterielExWarehouseHistoryDO::getOrderCode, id);

        kisMaterielExWarehouseRecycleMapper.delete(KisMaterielExWarehouseRecycleDO::getOrderCode, id);

        orderDetailMapper.delete(OrderDetailDO::getOrderCode, id);

        productProcessCompletedMapper.delete(ProductProcessCompletedDO::getOrderId, id);

        deptCompletedLogMapper.delete(DeptCompletedLogDO::getOrderCode, id);

        productionCodeMapper.delete(ProductionCodeDO::getOrderCode, id);

        weightHistoryMapper.delete(WeightHistoryDO::getOrderCode, id);
    }

    private void validateOrderExists(String id) {
        if (orderMapper.selectById(id) == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
    }

    @Override
    public OrderDO getOrder(String id) {
        return orderMapper.selectById(id);
    }

    @Override
    public OrderDO getOrder(String id, String code) {
        QueryWrapper<OrderDO> orderDOQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(id)) {
            orderDOQueryWrapper.eq("id", id);
        }
        if (StringUtils.isNotBlank(code)) {
            orderDOQueryWrapper.eq("code", code);
        }
        return orderMapper.selectOne(orderDOQueryWrapper);
    }

    @Override
    public PageResult<OrderDO> getOrderPage(OrderPageReqVO pageReqVO) {
        return orderMapper.selectPage(pageReqVO);
    }




    @Override
    public List<OrderDO> selectSavedList(Map<String, Object> params) {
        List<OrderDO> list = orderMapper.selectSavedList(params);
        return list;
    }

    @Override
    public void insertRecord(List<OrderDO> insertList) {
        // 插入
        if (null != insertList && insertList.size() > 0) {
            orderMapper.insertList(insertList);
        }
    }

    @Override
    public void updateRecord(List<OrderDO> updateList) {
        // 更新
        if (null != updateList && updateList.size() > 0) {
            LocalDateTime today = LocalDateTimeUtil.now();
            for (OrderDO data : updateList) {
                data.setUpdateTime(today);
            }
            orderMapper.updateList(updateList);
        }
    }

    @Override
    public List<PreparationVO> createPreparationByOrderCode(Map<String, Object> params) {
        String orderCode = (String) params.get("orderCode");
        List<String> flexList = orderMapper.selectFlexListByOrderCode(params);
        List<PreparationVO> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(flexList)) {
            for (String type : flexList) {
                List<PreparationVO> preparationVOS = kisBomMapper.selectBomListByType(type);
                if (CollectionUtil.isNotEmpty(preparationVOS)) {
                    preparationVOS = preparationVOS.stream().map(c -> {
                        c.setOrderCode(orderCode);
                        return c;
                    }).collect(Collectors.toList());
                    result.addAll(preparationVOS);
                }
            }
        }

        if (CollectionUtil.isNotEmpty(result)) {
            result = result.stream().distinct().collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<OrderFlexNumVO> selectTypeNumByOrderCode(Map<String, Object> params) {
        List<OrderFlexNumVO> orderFlexNumVOS = orderMapper.selectTypeNumByOrderCode(params);
        return orderFlexNumVOS;
    }

    public Integer getUnfinishedNum(Long totalNum, String orderCode) {

        QueryWrapper<DeptCompletedLogDO> deptCompletedLogDOQueryWrapper = new QueryWrapper<>();
        deptCompletedLogDOQueryWrapper.eq("order_code", orderCode);
        deptCompletedLogDOQueryWrapper.eq("dept_name", "C课");

        Long deptFinishedCount = deptCompletedLogMapper.selectCount(deptCompletedLogDOQueryWrapper);
        Long deptUnfinishedCount = totalNum - deptFinishedCount;
        return deptUnfinishedCount.intValue();
    }

    @Override
    public PageResult<OrderRespVO> getOrderAndDispatchList(OrderPageReqVO pageReqVO) {
        Page<OrderPageReqVO> page = new Page(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<OrderRespVO> list = orderMapper.getOrderAndDispatchList(page, pageReqVO);

        if(list != null){
            for(OrderRespVO orderRespVO : list){
                LocalDateTime orderDate = orderRespVO.getOrderDate();
                String orderDateStr = DateUtil.format(orderDate, "yyyy-MM-dd");
                orderRespVO.setOrderDateStr(orderDateStr);
                orderRespVO.setUnfinishedNum(getUnfinishedNum(orderRespVO.getTotalNum(), orderRespVO.getId()));
            }
        }

        PageResult<OrderRespVO> pageResult = new PageResult<>(list, page.getTotal());
        return pageResult;
    }

}